﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.Three
{

    public class DataView
    {
        public byte[] buffer;
        public int byteOffset;
        public int byteLength;
        public int nextOffset = 0;
        public bool littleEndian;
        public DataView(byte[] buffer, int byteOffset, int byteLength, bool littleEndian = true)
        {
            this.buffer = buffer;
            this.byteOffset = byteOffset;
            this.byteLength = byteLength;
            this.littleEndian = littleEndian;
        }

        public DataView(byte[] buffer, int byteOffset = 0)
        {
            this.buffer = buffer;
            this.byteOffset = byteOffset;
        }
        private byte[] bytes = new byte[8];
        public uint getUint32(int offset, bool littleEndian = true)
        {
            if (littleEndian == false)
            {
                var ofs = byteOffset + offset;
                bytes[0] = buffer[ofs + 3];
                bytes[1] = buffer[ofs + 2];
                bytes[2] = buffer[ofs + 1];
                bytes[3] = buffer[ofs + 0];
                return  BitConverter.ToUInt32(bytes, 0);
            }
            else
                return BitConverter.ToUInt32(buffer, byteOffset + offset);
        }
        public ushort getUint16(int offset, bool littleEndian = true)
        {
            return BitConverter.ToUInt16(buffer, byteOffset + offset);
        }
        public float getFloat32(int offset, bool littleEndian = true)
        {
            return BitConverter.ToSingle(buffer, byteOffset + offset);
        }
        public byte getUint8(int offset)
        {
            return buffer[byteOffset + offset];
        }
        public uint nextUint32()
        {
            var data = BitConverter.ToUInt32(buffer, byteOffset + nextOffset);
            nextOffset += 4;
            return data;
        }
        public int nextInt32()
        {
            var data = BitConverter.ToInt32(buffer, byteOffset + nextOffset);
            nextOffset += 4;
            return data;
        }
        public ulong nextUint64()
        {
            var data = this.getUint32(this.nextOffset, this.littleEndian) + (2 << 32) * (ulong)this.getUint32(this.nextOffset + 4, this.littleEndian);
            nextOffset += 8;
            return data;
        }
        public ushort nextUint16()
        {
            var data = BitConverter.ToUInt16(buffer, byteOffset + nextOffset);
            nextOffset += 2;
            return data;
        }
        public byte nextUint8()
        {
            var data = buffer[byteOffset + nextOffset];
            nextOffset += 1;
            return data;
        }
        public DataView skip(int skipOfsset)
        {
            nextOffset += skipOfsset;
            return this;
        }

        public byte[] scan(int maxByteLength, byte term = 0x00)
        {
            var byteOfs = this.nextOffset;
            var byteLen = 0;
            while (this.getUint8(this.nextOffset) != term && byteLen < maxByteLength)
            {
                byteLen++;
                this.nextOffset++;
            }

            if (byteLen < maxByteLength) this.nextOffset++;

            return this.buffer.slice2<byte>(this.byteOffset + byteOfs, byteLen);
        }
    }

}
